import {Injectable} from '@angular/core';
import {HttpService} from "./http.service";
import {Broadcast, CapacityChangeEvent, FileAddEvent, FileDeleteEvent, FileRenameEvent} from "../model/broadcast-dto";
import {AppContextService} from "./app-context.service";
import {PathService} from "./path.service";
import {FileViewService} from "./file-view.service";
import {CapacityChangeService} from "./capacity-change.service";

declare var Buffer: any
declare var SockJS: any
declare var EventBus: any

@Injectable({
  providedIn: 'root'
})
export class SockJsService {

  eb: any | null = null

  constructor(
    private server: HttpService,
    private ctx: AppContextService,
    private pathService: PathService,
    private fileViewService: FileViewService,
    private capacityService: CapacityChangeService
  ) {
  }

  initSockJs() {
    const options = {
      vertxbus_reconnect_attempts_max: Infinity, // 重连尝试最多次数
      vertxbus_reconnect_delay_min: 1000, // 在第一次尝试重连之前的初始延迟（单位为毫秒）
      vertxbus_reconnect_delay_max: 5000, // 尝试重连之间的最大延迟（单位为毫秒）
      vertxbus_reconnect_exponent: 2, // 指数退避因子
      vertxbus_randomization_factor: 0.5 // 介于0和1之间的随机因子
    }

    const ref = this
    this.eb = new EventBus(this.server.baseUrl() + '/eventbus', options)
    this.eb.enableReconnect(true);
    this.eb.onopen = function () {
      console.log('eventbus连接成功')
      ref.eb.registerHandler('file.add', function (error: any, message: any) {
        console.log('文件创建')
        ref.onAddFile(SockJsService.parseJson(message.body) as Broadcast<FileAddEvent>)
      })
      ref.eb.registerHandler('file.delete', function (error: any, message: any) {
        console.log('文件删除')
        ref.onDeleteFile(SockJsService.parseJson(message.body) as Broadcast<FileDeleteEvent>)
      })
      ref.eb.registerHandler('file.rename', function (error: any, message: any) {
        console.log('文件重命名')
        ref.onRenameFile(SockJsService.parseJson(message.body) as Broadcast<FileRenameEvent>)
      })
      ref.eb.registerHandler('file.capacity', function (error: any, message: any) {
        console.log('容量变化')
        ref.onCapacityChange(SockJsService.parseJson(message.body) as Broadcast<CapacityChangeEvent>)
      })
    }
  }

  private onDeleteFile(event: Broadcast<FileDeleteEvent>) {
    const fileList = this.ctx.currentFiles
    if (fileList == undefined || fileList.length == 0) {
      return;
    }

    const payload = event.payload
    if (!this.pathService.matchCurrentPath(payload.path)) {
      return
    }

    const currentFile = this.ctx.currentFile
    fileList.forEach((f, idx, array) => {
      if (f.filename == payload.filename) {
        array.splice(idx, 1)
      }
    })

    if (currentFile != undefined) {
      if (currentFile.filename == payload.filename) {
        this.ctx.release()
      }
    }
  }

  private onAddFile(event: Broadcast<FileAddEvent>) {
    const fileList = this.ctx.currentFiles
    if (fileList == undefined)
      return

    const payload = event.payload
    if (!this.pathService.matchCurrentPath(payload.path)) {
      return
    }

    let exists = false
    const theFile = payload.file

    fileList.forEach((f) => {
      if (f.filename === theFile.filename)
        exists = true
    })

    if (!exists) {
      fileList.push(this.fileViewService.fileResolve(theFile))
    }
  }

  private onRenameFile(event: Broadcast<FileRenameEvent>) {
  }

  private onCapacityChange(event: Broadcast<CapacityChangeEvent>) {
    this.capacityService.change.next(event.payload)
  }

  private static parseJson(json: string): any {
    return JSON.parse(json)
  }
}
